import { _decorator, AudioClip, AudioSource, Color, Component, Button, Widget, EventHandler, find, instantiate, JsonAsset, Label, Node, Prefab, Sprite, Tween, tween, UITransform, Vec3 } from 'cc';
const { ccclass, property } = _decorator;
import { Utils } from './Utils';
import { Player } from './Player';
import { Blueprint } from './Blueprint';
import { PixelItem } from './PixelItem';
import { Monster } from './Monster';
import { ColorBoard } from './ColorBoard';
import { GameManager } from './GameManager';
import { EquipmentBpBox } from './EquipmentBpBox';


@ccclass('Intro')
export class Intro extends Component {
    @property({type: Node})
    blueScreenNode: Node = null!

    @property({type: Node})
    introLabelNode: Node = null!

    @property({type: Node})
    blueprintNode: Node = null!

    @property({type: JsonAsset})
    equipmentJsonAsset: JsonAsset = null!

    @property({type: JsonAsset})
    monsterJsonAsset: JsonAsset = null!

    @property({type: Node})
    playerNode: Node = null!

    @property({type: Node})
    playerProgressBarNode: Node = null!

    @property({type: Node})
    bossDoorNode: Node = null!
    
    @property({type: Node})
    joystickNode: Node = null!

    @property({type: Node})
    attackButtonNode: Node = null!

    @property({type: Node})
    paintButtonNode: Node = null!

    @property({type: Node})
    backpackButtonNode: Node = null!

    @property({type: Node})
    colorBaordScrollViewNode: Node = null!

    @property({type: Node})
    ToolBoxScrollViewNode: Node = null!

    @property({type: Prefab})
    pixelItemPrefab: Prefab = null!

    @property({type: Prefab})
    monsterPrefab: Prefab = null!

    @property({type: AudioClip})
    acquireAudio: AudioClip = null!

    @property({type: AudioClip})
    blueScreenAudio: AudioClip = null!

    @property({type: AudioClip})
    showAudio: AudioClip = null!

    @property({type: AudioClip})
    clickAudio: AudioClip = null!

    utils: Utils = new Utils()
    audioSource: AudioSource = null!
    canvasUITransform: UITransform = null!

    equipmentJsonData: object = null!
    monsterJsonData: object = null!
    triangleTipTweeen: Tween<Node> = null!

    introIndex: number = 0
    isCurrentIntroFinished: boolean = false
    introTextArray: Array<string> = ['勇士！我们终于找到你了！', '抱歉把你设备弄蓝屏T-T。', '这个世界已经被大魔王摧残太久了。', '请一定要帮助我们打败它！',
                                     '这是你的化身，一名伟大的像素勇士！', '可以用左下角的摇杆移动它。', '要挑战大魔王，武器可不能少。',
                                     '我这里有一张木棍制作图，你先拿着，不要客气。', '有了制作图，就可以去收集相应的颜料。', '然后就可以制作并使用图上的武器了！',
                                     '看！出现了制作木棍所需的颜料，快去收集吧。', '现在点击下方的绘画图标开始制作木棍。', '危险！大魔王派来了一个怪物，快消灭它！',
                                     '勇士，你真的好厉害哇！', '我们的像素世界就靠你拯救了！', '穿过上方的门就可以去挑战大魔王了。', '当然你也可以在这里先修炼下自己。',
                                     '勇士，拜托了！！！', '啊！大魔王发现我了！勇士！救...']

    onLoad() {
        this.checkIsIntroExecuted()
    }

    start() {
        this.initComponents()
        this.initJsonData()
        this.initTouchEvents()
        this.showBlueScreen()
    }

    /** 
     * @zh
     * 初始化组件。
    */
    initComponents() {
        this.utils = this.node.getComponent(Utils)
        this.audioSource = this.getComponent(AudioSource)
        this.canvasUITransform = this.node.getComponent(UITransform)
    }

    /** 
     * @zh
     * 初始化Json数据变量。
    */
    initJsonData() {
        this.equipmentJsonData = this.equipmentJsonAsset.json
        this.monsterJsonData = this.monsterJsonAsset.json
    }

    /** 
     * @zh
     * 初始化组触摸事件。
    */
    initTouchEvents() {
        this.node.on(Node.EventType.TOUCH_END, this.onTouchEnd, this)
    }

    /** 
     * @zh
     * 在画布上点击后执行的逻辑。
    */
    onTouchEnd() {
        // 如果当前文本还没显示完毕，则直接返回
        if (!this.isCurrentIntroFinished) {
            return
        }

        // 如果所有文本显示完毕，则表示引导已经结束
        if (this.introIndex >= this.introTextArray.length) {
            this.doWhenIntroIsOver()
            return
        }

        // 隐藏必要的节点
        this.hideBlueScreen()
        this.hideTriangleTip()

        // 显示文本
        this.isCurrentIntroFinished = false
        this.utils.showText(this.introLabelNode.getComponent(Label), this.introTextArray[this.introIndex], ()=>{
            // 显示小三角提示
            this.showTriangleTip()

            // 非以下步骤文本显示完毕，就可以点击屏幕快速跳过，其他步骤可能需要等上几秒
            if ([4, 5, 7, 10, 11, 12, 15].indexOf(this.introIndex) == -1) {
                this.setCurrentIntroFinished(0.1)
            }

            // 在这一步显示主角
            if (this.introIndex == 4) {
                this.showPlayer()
            }

            // 显示摇杆
            if (this.introIndex == 5) {
                this.joystickNode.active = true
                this.joystickNode.getComponent(Widget).updateAlignment()
                this.setCurrentIntroFinished(1)
            }

            // 显示木棍蓝图
            if (this.introIndex == 7) {
                // 延迟出现，给玩家一点阅读文本的时间
                this.scheduleOnce(()=>{
                    this.showStickBlueprint()
                    this.setCurrentIntroFinished(2)
                }, 0.1)

                this.scheduleOnce(()=>{
                    this.hideStickBlueprint()
                }, 2)
            } 

            // 出现颜料
            // 看！屏幕上出现了制作木棍所需的颜料。
            if (this.introIndex == 10) {
                this.showPixelItemsForStick()
                this.checkIfPixelItemGotEaten()
            }

            // 现在点击下方的绘画图标开始制作木棍
            if (this.introIndex == 11) {
                this.showPaintButton()
                this.checkIfPlayerHasStickWeapon()
            }

            // 危险！大魔王派来了一个小怪，快消灭它！
            if (this.introIndex == 12) {
                this.showMonster()
                this.checkIfPlayerOrMonsterDead()
                this.attackButtonNode.active = true
            }

            // 穿过上方的门就可以去挑战大魔王了
            if (this.introIndex == 15) {
                this.bossDoorNode.active = true
                this.setCurrentIntroFinished(2)
            }

            // 索引+1
            this.introIndex++

        }, true, 0.08)
    }

    /** 
     * @zh
     * 检查引导是否执行过。
    */
    checkIsIntroExecuted() {
        if (localStorage.getItem('lp-intro-over')) {
            this.enabled = false
            this.node.getComponent(GameManager).enabled = true
            this.blueScreenNode.active = false
            this.attackButtonNode.active = true
            this.joystickNode.active = true
            this.playerNode.active = true
            this.playerProgressBarNode.active = true
            this.introLabelNode.active = false
            this.bossDoorNode.active = true
            find('Canvas/Blueprint Background/Button Layout/Equip Button').active = true
            find('Canvas/Blueprint Background/Button Layout/Store Button').active = true
            find('Canvas/Blueprint Background/Equipment BP Box').active = true
            find('Canvas/Blueprint Background/Auxiliary Function Box').active = true

            this.backpackButtonNode.active = true
            this.paintButtonNode.active = true

            // 移除Intro.ts中的onPaintButtonClicked事件函数
            // 添加GameManager中的onPaintButtonClicked事件函数
            this.paintButtonNode.getComponent(Button).clickEvents.shift()   
            let eventHandler = new EventHandler()
            eventHandler.target = this.node
            eventHandler.component = 'GameManager'
            eventHandler.handler = 'onPaintButtonClicked'
            this.paintButtonNode.getComponent(Button).clickEvents.push(eventHandler)    
        }

        // 如果引导没有结束，要清空引导期间获得的木棍物品
        else {
            localStorage.removeItem('lp-color-data')
            localStorage.removeItem('lp-equipment-bp-box')
        }
    }

    /** 
     * @zh
     * 引导结束时的操作。
    */
    doWhenIntroIsOver() {
        localStorage.setItem('lp-intro-over', '1')
        this.checkIsIntroExecuted()
    }

    /** 
     * @zh
     * 可以延迟设置，防止用户点击太快。
    */
    setCurrentIntroFinished(delayedTime:number = 1) {
        if (delayedTime <= 0) {
            this.isCurrentIntroFinished = true
        }
        else {
            this.scheduleOnce(()=>{this.isCurrentIntroFinished = true}, delayedTime)
        }
    }

    /** 
     * @zh
     * 显示蓝屏。
    */
    showBlueScreen() {
        this.audioSource.playOneShot(this.blueScreenAudio)
        this.setCurrentIntroFinished(0.5)
    }

    /** 
     * @zh
     * 隐藏蓝屏。
    */
    hideBlueScreen() {
        this.blueScreenNode.active = false
    }

    /** 
     * @zh
     * 显示主角。
    */
    showPlayer() {
        // Label节点往上移动，Player节点显示出来
        tween(this.introLabelNode).by(0.5, {'position': new Vec3(0, 40, 0)})
                                  .call(()=>{
                                    this.setCurrentIntroFinished(1)
                                    this.playerNode.active = true
                                    this.playerProgressBarNode.active = true
                                    this.playerNode.getComponent(Player).blink()
                                    this.audioSource.playOneShot(this.showAudio, 0.5)
                                  })
                                  .start()
    }

    /** 
     * @zh
     * 显示小三角提示。
    */
    showTriangleTip() {
        let triangleTipNode = this.introLabelNode.children[0]
        triangleTipNode.active = true

        // 设置小三角在文本右侧
        let triangleTipNodeWidth = triangleTipNode.getComponent(UITransform).width
        let introLabelNodeWidth = this.introLabelNode.getComponent(UITransform).width
        triangleTipNode.setPosition(introLabelNodeWidth/2+triangleTipNodeWidth, 0, 0)
        
        // 上下运动
        this.triangleTipTweeen = tween(triangleTipNode).by(0.2, {'position': new Vec3(0, 10, 0)})
                                                       .by(0.2, {'position': new Vec3(0, -10, 0)})
                                                       .union()
                                                       .repeatForever()
                                                       .start()
    }

    /** 
     * @zh
     * 隐藏小三角提示。
    */
    hideTriangleTip() {
        let triangleTipNode = this.introLabelNode.children[0]
        triangleTipNode.active = false
        if (this.triangleTipTweeen) {
            this.triangleTipTweeen.stop()
        }
    }

    /** 
     * @zh
     * 显示木棍制作图。
    */
    showStickBlueprint() {
        this.blueprintNode.getComponent(Blueprint).draw(this.equipmentJsonData['stick'])
        this.blueprintNode.parent.active = true
        this.blueprintNode.parent.setScale(0, 0, 1)
        tween(this.blueprintNode.parent).to(0.3, {'scale': new Vec3(0.65, 0.65, 1)}).start()

        // 制作图滚动列表中添加了一个木棍制作图
        find('Canvas/Blueprint Background/Equipment BP Box').getComponent(EquipmentBpBox).updateEquipmentBpBoxInfo('ADD', 'stick', 1, this.equipmentJsonData['stick'])

        this.audioSource.playOneShot(this.acquireAudio)
    }

    /** 
     * @zh
     * 隐藏木棍制作图。
    */
    hideStickBlueprint() {
        this.blueprintNode.parent.active = false
        for (let i=0; i<this.blueprintNode.children.length; i++) {
            this.blueprintNode.children[i].getComponent(Sprite).color = new Color().fromHEX('ffffff')
        }
    }

    /** 
     * @zh
     * 显示像素块(颜料)。
    */
    showPixelItemsForStick() {
        // 获取木棍所需像素颜色及对应数量
        let colorInfo = {}
        let points = this.equipmentJsonData['stick']['points']

        for (let i=0; i< points.length; i++) {
            let colorHex = points[i][2]
            if (colorHex in colorInfo) {
                colorInfo[colorHex] += 1
            }
            else {
                colorInfo[colorHex] = 1
            }
        }

        for (let colorHex in colorInfo) {
            let pixelItemX = 0
            let pixelItemY = 0
            if (this.playerNode.position.x <= 0) {
                pixelItemX = Math.random() * this.canvasUITransform.width / 4 + this.playerNode.getComponent(UITransform).width*2
            }
            else {
                pixelItemX = Math.random() * -this.canvasUITransform.width / 4 - this.playerNode.getComponent(UITransform).width*2
            }

            if (this.playerNode.position.y <= 0) {
                pixelItemY = Math.random() * this.canvasUITransform.height / 4 + this.playerNode.getComponent(UITransform).height*2
            }
            else {
                pixelItemY = Math.random() * -this.canvasUITransform.height / 4 - this.playerNode.getComponent(UITransform).height*2
            }
            
            let pixelItem = this.spawnPixelItem(colorHex, colorInfo[colorHex], new Vec3(pixelItemX, pixelItemY, 1))
            this.node.addChild(pixelItem)
        }
    }

    /** 
     * @zh
     * 根据颜色，数量，位置生成像素块(颜料)。
    */
    spawnPixelItem(colorHex: string, pixelNum: number, pos: Vec3) {
        let pixelItem = instantiate(this.pixelItemPrefab)
        pixelItem.getComponent(PixelItem).pixelNum = pixelNum
        pixelItem.getComponent(Sprite).color = new Color().fromHEX(colorHex)
        pixelItem.setPosition(pos)
        pixelItem.getComponent(PixelItem).enabled = true
        pixelItem.setScale(1+0.1*pixelNum, 1+0.1*pixelNum, 1)
        return pixelItem
    }

    /** 
     * @zh
     * 检查玩家是否有把颜料吃掉，吃掉的话则显示下一步。
    */
    checkIfPixelItemGotEaten() {
        let callback = () => {
            if (!find('Canvas/pixelItem')) {
                this.unschedule(callback)
                this.setCurrentIntroFinished(0)
                this.onTouchEnd() // 吃完颜料后直接模拟点击一次
            }
        }

        this.schedule(callback, 0.1)
    }

    /** 
     * @zh
     * 显示绘画按钮。
    */
    showPaintButton() {
        this.paintButtonNode.active = true
        tween(this.paintButtonNode).to(0.4, {'scale': new Vec3(1.2, 1.2, 1)})
                                   .to(0.4, {'scale': new Vec3(1, 1, 1)})
                                   .union()
                                   .repeat(3)
                                   .start()
    }

    /** 
     * @zh
     * 当玩家点击了绘制按钮。
    */
    onPaintButtonClicked() {
        // 显示或隐藏相关节点
        if (this.colorBaordScrollViewNode.active) {
            this.blueprintNode.parent.active = false
            this.colorBaordScrollViewNode.active = false
            this.ToolBoxScrollViewNode.active = false
            this.joystickNode.active = true
            if (this.introIndex >= 13) {
                this.attackButtonNode.active = true
            }
        }
        else {
            this.blueprintNode.parent.active = true
            find('Canvas/Blueprint Background/Button Layout/Equip Button').active = true
            find('Canvas/Blueprint Background/Equipment BP Box').active = true

            this.colorBaordScrollViewNode.active = true
            this.ToolBoxScrollViewNode.active = true
            this.blueprintNode.parent.setSiblingIndex(5000)
            this.colorBaordScrollViewNode.setSiblingIndex(5000)
            this.ToolBoxScrollViewNode.setSiblingIndex(5000)
            this.joystickNode.active = false
            this.attackButtonNode.active = false
            this.introLabelNode.getComponent(Label).string = ''     // 引导阶段绘制时清空引导文本
            this.hideTriangleTip()
        }

        this.audioSource.playOneShot(this.clickAudio)
    }

    /** 
     * @zh
     * 检查玩家制作出了木棍武器，是的话显示下一步引导。
    */
    checkIfPlayerHasStickWeapon() {
        let callback = () => {
            if (this.playerNode.getChildByName('Weapon').getComponent(Sprite).spriteFrame) {
                this.unschedule(callback)
                this.setCurrentIntroFinished(0)
                this.onTouchEnd() // 吃完颜料后直接模拟点击一次
            }
        }
        this.schedule(callback, 0.2)
    }

    /** 
     * @zh
     * 生成怪物。
    */
    showMonster() {
        let monster = instantiate(this.monsterPrefab)
        let randomIndex = Math.floor(Math.random() * Object.keys(this.monsterJsonData).length)
        let monsterInfo = this.monsterJsonData[`monster${randomIndex}`]
        monster.getComponent(Monster).setMonsterInfo(monsterInfo)
        this.node.addChild(monster)
    }

    /** 
     * @zh
     * 检查主角或者怪物是否被干掉了。
    */
    checkIfPlayerOrMonsterDead() {
        let callback = () => {
            if (!find('Canvas/monster')) {
                this.unschedule(callback)
                this.setCurrentIntroFinished(0)
                this.onTouchEnd() // 吃完颜料后直接模拟点击一次
            }
            else if (this.playerNode.getComponent(Player).isDead) {
                this.unschedule(callback)
                this.utils.showText(this.introLabelNode.getComponent(Label), '勇士，不打紧，我这药管够。', ()=>{
                    // 显示小三角提示
                    this.showTriangleTip()
                    this.checkIfPlayerCured()
                    
                    // 添加治疗药水颜料，黑色颜料数量为20，红色为8
                    this.colorBaordScrollViewNode.getComponent(ColorBoard).updateColorData('cbdbfc', 20)
                    this.colorBaordScrollViewNode.getComponent(ColorBoard).updateColorData('ff0000', 8)

                    find('Canvas/Blueprint Background/Equipment BP Box').getComponent(EquipmentBpBox).updateEquipmentBpBoxInfo('ADD', 'cure', 1, this.equipmentJsonData['cure'])

                    // 显示治疗药水图
                    this.scheduleOnce(()=>{
                        if (!this.blueprintNode.parent.active) {
                            this.onPaintButtonClicked()
                        }
                    }, 1.5)

             
                })
            }
        }
        this.schedule(callback, 0.2)
    }

    /** 
     * @zh
     * 检查主角是否被救活了。
    */
    checkIfPlayerCured() {
        let callback = () => {
            if (!this.playerNode.getComponent(Player).isDead) {
                this.unschedule(callback)
                this.checkIfPlayerOrMonsterDead()
            }
        }
        this.schedule(callback, 0.2)
    }
}


